import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;

public class CustomConnectionPool {
	private String dbURL;
	private int capacity;
	private BlockingQueue<Connection> pool;

	/**
	 * Creates connection pool with the specified capacity.
	 * 
	 * @param capacity
	 */
	CustomConnectionPool(String dbURL, int capacity) {
		this.capacity = capacity;
		this.dbURL = dbURL;
		initQueue();
	}

	/**
	 * Returns connection if available or blocks until connection becomes
	 * available in the pool.
	 * 
	 * @return connection
	 * @throws InterruptedException
	 */
	public Connection getConnection() throws InterruptedException {
		return pool.take();
	}

	/**
	 * Returns connection if available or blocks until connection becomes
	 * available in the pool or waiting exceeds specified timeout.
	 * 
	 * @param timeout
	 *            how long to wait before giving up, in units of <tt>unit</tt>
	 * @param unit
	 *            a <tt>TimeUnit</tt> determining how to interpret the
	 *            <tt>timeout</tt> parameter
	 * @return connection
	 * @throws InterruptedException
	 */
	public Connection getConnection(long timeout, TimeUnit unit)
			throws InterruptedException {
		return pool.poll(timeout, unit);
	}

	/**
	 * Returns connection back to the pool.
	 * 
	 * @param connection
	 *            connection
	 */
	public void releaseConnection(Connection connection) {
		try {
			pool.add(connection);
		} catch (IllegalStateException e) {
			System.err
					.println("Can't release connection properly. Connection pool is full.");
		}
	}

	private void initQueue() {
		try {
			Class.forName("com.mysql.jdbc.Driver").newInstance();
			pool = new ArrayBlockingQueue<>(capacity);
			for (int i = 0; i < capacity; i++) {
				Connection connection = DriverManager.getConnection(dbURL);
				pool.add(connection);
			}
		} catch (InstantiationException | IllegalAccessException
				| ClassNotFoundException | SQLException e) {
			System.err
					.println("Can't initialize connection pool for some reason.");
			throw new RuntimeException(e);
		}
	}
}
